
var url_module = require('url');
const fs = require("fs");
const path = require("path");

//这个插件报废,必须引入大量node_modules
let curDir= process.cwd() +"/static";
let pure_cur_dir= "https://minglie.gitee.io/ming_node_vite_vue"


M.requireVite =async function (url,noCache) {
    //如果需要缓存
    let fileName=M.getFileNameByUrl(url);
    let cacheFilePath= path.join(M._node_lib_path,fileName);
    if(!noCache){
        if(fs.existsSync(cacheFilePath)){
            try {
                if(fileName.startsWith("compiler")){
                    return require(cacheFilePath)
                }else {
                    return M.readFile(cacheFilePath)
                }

            }catch (e){
                console.error(e)
                return M.readFile(cacheFilePath)
            }

        }
    }
    if(M._globle_lib_cacheMap[url]){
        return M._globle_lib_cacheMap[url];
    }
    let ht = "http";
    if (url.startsWith("https")) {
        ht = "https";
    }
    console.log("req require remote url:", url);
    let promise = new Promise(function (reslove, reject) {
        require(ht).get(url, function (req, res) {
            var d = '';
            req.on('data', (data) => {
                d += data;
            });
            req.on('end', () => {
                let r = "";
                try {
                    if(fileName.endsWith(".js")){
                        //如果需要缓存
                        if(!noCache){
                            if (!fs.existsSync(M._node_lib_path)) {
                                fs.mkdirSync(M._node_lib_path);
                            }
                            if(fileName.startsWith("compiler")) {
                                M.writeFile(cacheFilePath, d);
                            }
                        }
                        r= d;
                    }else {
                        r = JSON.parse(d)
                    }
                } catch (e) {
                    r = d;
                }
                M._globle_lib_cacheMap[url]=r;
                reslove(r);
            });
            req.on('error', (e) => reject(e.message));
        })
    });
    return promise;
}

this.viteFilter= async (req,res)=>{
    const compilerSfc =await M.requireVite("https://minglie.gitee.io/ming_node_vite_vue/node_modules/@vue/compiler-sfc/dist/compiler-sfc.cjs.js");
    const compilerDom =await M.requireVite("https://minglie.gitee.io/ming_node_vite_vue/node_modules/@vue/compiler-dom/dist/compiler-dom.cjs.js");

    const {url}=req;
    const query= url_module.parse(req.url, true).query
    // console.log("url: ",query);
    // console.log("<====",req.url,req.params)
    // / => index.html
    if (url === "/") {
        let content = fs.readFileSync(curDir+"/index.html", "utf-8");
        // 入口文件 加入环境变量
        content = content.replace(
            "<script",
            `
      <script>
          window.process = {env: { NODE_ENV: 'dev' }}
      </script>
      <script
      `
        );
        res.renderHtml(content)
    }

    // *.js => src/*.js
    else if (url.endsWith(".js")) {
        // /src/main.js => 代码文件所在位置/src/main.js
        const p = path.resolve(curDir, url.slice(1));
        const content = fs.readFileSync(p, "utf-8");
        res.renderJs(rewriteImport(content));
    }

        // 第三方库的支持
    // /@modules/vue => node_modules
    else if (url.startsWith("/@modules")) {
        // /@modules/vue  => 代码的位置/node_modules/vue/ 的 es模块入口
        // const prefix = path.resolve(
        //     pure_cur_dir,
        //     "node_modules",
        //     url.replace("/@modules/", "")
        // );
        const prefix=pure_cur_dir+"/node_modules/"+ url.replace("/@modules/", "")
        // 读取package.json的module属性
        // dist/vue.runtime.esm-bundler.js
        let module =await M.requireVite(prefix + "/package.json");
        module=module.module;

        const p = prefix+"/"+module;
        const ret =await M.requireVite(p);
        res.renderJs(rewriteImport(ret));
    }

        // 支持SFC组件  单文件组件
    // /*.vue =>
    else if (url.indexOf(".vue") > -1) {
        //console.log("QQQQQQQQQQQQQ")
        // /*.vue?type=template
        const p = path.resolve(curDir, url.split("?")[0].slice(1));
        const { descriptor } = compilerSfc.parse(fs.readFileSync(p, "utf-8"));
        // console.log("descriptor", descriptor);
        //console.log("@@@@",query)

        if (!query.type) {
            //console.log("QQQQQQQQQQQQQ11111111")

            // 第一步 vue文件 => template script  (compiler-sfc)
            // descriptor.script => js + template生成render部分
            res.renderJs( `
    ${rewriteImport(
                descriptor.script.content.replace("export default ", "const __script = ")
            )}
    import { render as __render } from "${url}?type=template"
    __script.render = __render
    export default __script
        `);
        } else {
            // console.log("WWWWWWWWWWWWWWWWWWWWWWW")
            // 第二步 template模板 => render函数   (compiler-dom)
            const template = descriptor.template;
            const render = compilerDom.compile(template.content, { mode: "module" });
            res.renderJs(rewriteImport(render.code));
        }
    }

    // css文件
    else if (url.endsWith(".css")) {
        const p = path.resolve(curDir, url.slice(1));
        const file = fs.readFileSync(p, "utf-8");

        // css 转化为 js代码
        // 利用js 添加一个 style标签
        const content = `
      const css = "${file.replace(/\n/g, "")}"
      let link = document.createElement('style')
      link.setAttribute('type', 'text/css')
      document.head.appendChild(link)
      link.innerHTML = css
      export default css
      `;
        res.renderJs(content);
    }
    // JSX语法
    // TS问题

    // vue => node_modules/***

    // 改写函数
    // 需要改写 欺骗一下浏览器 'vue' => '/@modules/vue  => 别名
    // from 'xxx'
    function rewriteImport(content) {
        // 正则
        return content.replace(/ from ['|"]([^'"]+)['|"]/g, function (s0, s1) {
            if (s1[0] !== "." && s1[1] !== "/") {
                // 是不是不是一个绝对路径或相对路径 / 或 ../ ./
                return ` from '/@modules/${s1}'`;
            } else {
                return s0;
            }
        });
    }
}
